﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using Sinacor.Infra.UI.Controls.SmartClient.BehaviorPolicy;
using Sinacor.Infra.UI.Controls.SmartClient.Validation;

namespace Sinacor.Infra.UI.Controls.SmartClient
{
	[DefaultProperty("Value")]
	public partial class SinacorTimePicker : Control, IValidatableObject, IEditBehaviorPolicy, IVisibilityBehaviorPolicy
	{
		int index;
		int? _sourceObjectHashCode;
		string DateMaskFormat = "__:__";
		bool _isOpen;
		List<DateTime> oldTime = new List<DateTime>();
		SinacorTextBox txtData;
		Button btnUp;
		Button btnDown;
		Button btnOpenPopUp;
		Grid grdPrinc;
		enmTypeSelection selection;
		BehaviorPolicyAdapter _behaviorPolicyAdapter;
		Popup PopUpTime = null;
		Button TitleHour = null;
		Button TitleMinute = null;
		ListBox hour = null;
		ListBox minute = null;
		Grid Time = null;
		Rectangle ret = null;
		enum enmTypeSelection
		{
			Hour,
			Minute
		}
		enum enmTypeAdjust
		{
			Increase,
			Decrease
		}
		internal BehaviorPolicyAdapter BehaviorPolicyAdapter
		{
			get { return _behaviorPolicyAdapter; }
			set { _behaviorPolicyAdapter = value; }
		}

		protected const string RangeValidationRuleName = "RangeValidator";
		protected const string RequiredValidationRuleName = "RequiredValidator";
		protected const string TimeValidationRuleName = "TimeValidator";
		protected static readonly DependencyProperty InternalDateProperty = DependencyProperty.Register("InternalDate", typeof(string), typeof(SinacorTimePicker), new UIPropertyMetadata(""));
		protected string InternalDate
		{
			get { return (string)GetValue(InternalDateProperty); }
			set { SetValue(InternalDateProperty, value); }
		}

		public static readonly DependencyProperty MinTimeProperty = DependencyProperty.Register("MinTime", typeof(DateTime), typeof(SinacorTimePicker), new UIPropertyMetadata(DateTime.MinValue, OnMinTimeChange));
		public static readonly DependencyProperty MaxTimeProperty = DependencyProperty.Register("MaxTime", typeof(DateTime), typeof(SinacorTimePicker), new UIPropertyMetadata(DateTime.MaxValue, OnMaxTimeChange));
		public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(DateTime?), typeof(SinacorTimePicker), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnValueChange));
		public static readonly DependencyProperty RequiredErrorMessageProperty = DependencyProperty.Register("RequiredErrorMessage", typeof(string), typeof(SinacorTimePicker), new UIPropertyMetadata("Infra.Controls.Message.CampoObrigatorio", OnRequiredErrorMessageChange));
		public static readonly DependencyProperty RangeOverflowErrorMessageProperty = DependencyProperty.Register("RangeOverflowErrorMessage", typeof(string), typeof(SinacorTimePicker), new UIPropertyMetadata("Infra.Controls.Message.HoraForaIntervalo", OnRangeOverFlowMessageChange));
		public static readonly DependencyProperty IsRequiredProperty = DependencyProperty.Register("IsRequired", typeof(bool), typeof(SinacorTimePicker), new UIPropertyMetadata(false, OnIsRequiredChange));
		public static readonly DependencyProperty InvalidDateErrorMessageProperty = DependencyProperty.Register("InvalidDateErrorMessage", typeof(string), typeof(SinacorTimePicker), new UIPropertyMetadata("Infra.Controls.Message.HoraInvalida", OnInvalidDateErrorMessageChange));
		public static readonly DependencyProperty CanValidateProperty = ValidationManager.CanValidateProperty.AddOwner(typeof(SinacorTimePicker));
		public static readonly DependencyProperty ValidationGroupProperty = ValidationManager.ValidationGroupProperty.AddOwner(typeof(SinacorTimePicker));
		public static readonly DependencyProperty ClearServiceErrorsProperty = ValidationManager.ClearServiceErrorsProperty.AddOwner(typeof(SinacorTimePicker));
		public static readonly DependencyProperty CausesValidationProperty = ValidationManager.CausesValidationProperty.AddOwner(typeof(SinacorTimePicker));
		public static readonly DependencyProperty ValidationTriggersProperty = ValidationManager.ValidationTriggersProperty.AddOwner(typeof(SinacorTimePicker));
		public static readonly DependencyProperty ValidationRulesProperty = ValidationManager.ValidationRulesProperty.AddOwner(typeof(SinacorTimePicker));
		public static readonly DependencyProperty HasErrorProperty = ValidationManager.HasErrorProperty.AddOwner(typeof(SinacorTimePicker));
		public static readonly DependencyProperty ErrorsProperty = ValidationManager.ErrorsProperty.AddOwner(typeof(SinacorTimePicker));
		public static readonly DependencyProperty ErrorTemplateProperty = ValidationManager.ErrorTemplateProperty.AddOwner(typeof(SinacorTimePicker));
		public static readonly DependencyProperty PolicyNameProperty = DependencyProperty.Register("PolicyName", typeof(string), typeof(SinacorTimePicker));
		public static readonly DependencyProperty IsChangeMonitoredProperty = ChangesMonitorManager.IsChangeMonitoredProperty.AddOwner(typeof(SinacorTimePicker));

		public bool IsRequired
		{
			get { return (bool)GetValue(IsRequiredProperty); }
			set { SetValue(IsRequiredProperty, value); }
		}
		public string InvalidDateErrorMessage
		{
			get { return (string)GetValue(InvalidDateErrorMessageProperty); }
			set { SetValue(InvalidDateErrorMessageProperty, value); }
		}
		public string RangeOverflowErrorMessage
		{
			get { return (string)GetValue(RangeOverflowErrorMessageProperty); }
			set { SetValue(RangeOverflowErrorMessageProperty, value); }
		}
		public string RequiredErrorMessage
		{
			get { return (string)GetValue(RequiredErrorMessageProperty); }
			set { SetValue(RequiredErrorMessageProperty, value); }
		}
		public DateTime? Value
		{
			get { return (DateTime?)GetValue(ValueProperty); }
			set 
			{
				SetValue(ValueProperty, value); 
				if (value == null)
				{
					this.UpdateTarget(SinacorTimePicker.ValueProperty);
					this.UpdateTarget(SinacorTimePicker.InternalDateProperty);
					this.txtData.UpdateTarget(TextBox.TextProperty);
				}
			}
		}
		public DateTime MaxTime
		{
			get { return (DateTime)GetValue(MaxTimeProperty); }
			set { SetValue(MaxTimeProperty, value); }
		}
		public DateTime MinTime
		{
			get { return (DateTime)GetValue(MinTimeProperty); }
			set { SetValue(MinTimeProperty, value); }
		}

		static void OnValueChange(DependencyObject obj, DependencyPropertyChangedEventArgs e)
		{
			//if (System.ComponentModel.DesignerProperties.GetIsInDesignMode(obj))
			//    return;
			SinacorTimePicker SNTP = (SinacorTimePicker)obj;
			if (SNTP.Value.HasValue)
			{
				SNTP.Value = new DateTime(2000, 01, 01, SNTP.Value.Value.Hour, SNTP.Value.Value.Minute, 00);
				SNTP.oldTime.Add(SNTP.Value.Value);
			}
				
		}
		static void OnMinTimeChange(DependencyObject obj, DependencyPropertyChangedEventArgs e)
		{
			//if (System.ComponentModel.DesignerProperties.GetIsInDesignMode(obj))
			//    return;
			SinacorTimePicker instance = obj as SinacorTimePicker;
			if (instance != null)
				instance.UpdateValitadions();
		}
		static void OnMaxTimeChange(DependencyObject obj, DependencyPropertyChangedEventArgs e)
		{
			//if (System.ComponentModel.DesignerProperties.GetIsInDesignMode(obj))
			//    return;
			SinacorTimePicker instance = obj as SinacorTimePicker;
			if (instance != null)
				instance.UpdateValitadions();
		}
		static void OnRequiredErrorMessageChange(DependencyObject obj, DependencyPropertyChangedEventArgs e)
		{
			//if (System.ComponentModel.DesignerProperties.GetIsInDesignMode(obj))
			//    return;
			SinacorTimePicker instance = obj as SinacorTimePicker;
			if (instance != null)
				instance.UpdateValitadions();
		}
		static void OnRangeOverFlowMessageChange(DependencyObject obj, DependencyPropertyChangedEventArgs e)
		{
			//if (System.ComponentModel.DesignerProperties.GetIsInDesignMode(obj))
			//    return;
			SinacorTimePicker instance = obj as SinacorTimePicker;
			if (instance != null)
				instance.UpdateValitadions();
		}
		static void OnInvalidDateErrorMessageChange(DependencyObject obj, DependencyPropertyChangedEventArgs e)
		{
			//if (System.ComponentModel.DesignerProperties.GetIsInDesignMode(obj))
			//    return;
			SinacorTimePicker instance = obj as SinacorTimePicker;
			if (instance != null)
				instance.UpdateValitadions();
		}
		static void OnIsRequiredChange(DependencyObject obj, DependencyPropertyChangedEventArgs e)
		{
			//if (System.ComponentModel.DesignerProperties.GetIsInDesignMode(obj))
			//    return;

			SinacorTimePicker instance = obj as SinacorTimePicker;
			if (instance != null)
				instance.UpdateValitadions();
		}

        protected override void OnGotFocus(RoutedEventArgs e)
        {
            base.OnGotFocus(e);

            if (txtData != null)
            {
                txtData.Focus();
            }
        }

		bool IEditBehaviorPolicy.IsEditable
		{
			get
			{
				return this.IsEnabled;
			}
			set
			{
				this.IsEnabled = value;
			}
		}
		bool IVisibilityBehaviorPolicy.IsVisible
		{
			get
			{
				return this.Visibility == Visibility.Visible;
			}
			set
			{
				this.Visibility = (value ? Visibility.Visible : Visibility.Collapsed);
			}
		}

		string IEditBehaviorPolicy.PropertyName
		{
			get { return "IsEnabled"; }
		}
		string IVisibilityBehaviorPolicy.PropertyName
		{
			get { return "Visibility"; }
		}

		public bool CanValidate
		{
			get { return (bool)GetValue(CanValidateProperty); }
		}
		public bool ClearServiceErrors
		{
			get { return (bool)GetValue(ClearServiceErrorsProperty); }
			set { SetValue(ClearServiceErrorsProperty, value); }
		}
		public bool CausesValidation
		{
			get { return (bool)GetValue(CausesValidationProperty); }
			set { SetValue(CausesValidationProperty, value); }
		}
		public bool HasError
		{
			get { return (bool)GetValue(HasErrorProperty); }
		}
		public bool Validate()
		{
			return ValidationManager.Validate(this);
		}
		public bool Validate(DependencyProperty property)
		{
			return ValidationManager.Validate(this, property);
		}
		public bool ValidateParentContainer()
		{
			return ValidationManager.ValidateParentContainer(this);
		}
		public bool IsChangeMonitored
		{
			get { return (bool)GetValue(IsChangeMonitoredProperty); }
			set { SetValue(IsChangeMonitoredProperty, value); }
		}
		public string ValidationGroup
		{
			get { return (string)GetValue(ValidationGroupProperty); }
			set { SetValue(ValidationGroupProperty, value); }
		}
		public string PolicyName
		{
			get
			{
				return (string)GetValue(PolicyNameProperty);
			}
			set
			{
				SetValue(PolicyNameProperty, value);
			}
		}
		public ValidationTriggerCollection ValidationTriggers
		{
			get { return (ValidationTriggerCollection)GetValue(ValidationTriggersProperty); }
		}
		public ValidationRuleCollection ValidationRules
		{
			get { return (ValidationRuleCollection)GetValue(ValidationRulesProperty); }
		}
		public ReadOnlyObservableCollection<ValidationError> Errors
		{
			get { return (ReadOnlyObservableCollection<ValidationError>)GetValue(ErrorsProperty); }
		}
		public ControlTemplate ErrorTemplate
		{
			get { return (ControlTemplate)GetValue(ErrorTemplateProperty); }
			set { SetValue(ErrorTemplateProperty, value); }
		}
		public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
		public override void OnApplyTemplate()
		{
			base.OnApplyTemplate();

			txtData = this.GetTemplateChild("Part_txtData") as SinacorTextBox;
			btnUp = this.GetTemplateChild("Part_btnAcima") as Button;
			btnDown = this.GetTemplateChild("Part_btnAbaixo") as Button;
			btnOpenPopUp = this.GetTemplateChild("Part_btPopUp") as Button;
			grdPrinc = this.GetTemplateChild("grdPrinc") as Grid;
			PopUpTime = this.GetTemplateChild("Part_PopUpTime") as Popup;
			TitleHour = this.GetTemplateChild("Part_Hour") as Button;
			TitleMinute = this.GetTemplateChild("Part_Minute") as Button;
			Time = this.GetTemplateChild("Part_SinacorTP") as Grid;
			ret = this.GetTemplateChild("Part_Ret") as Rectangle;
			hour = this.GetTemplateChild("Part_ListHour") as ListBox;
			minute = this.GetTemplateChild("Part_ListMinute") as ListBox;
			PopUpTime.Closed += new EventHandler(PopUpTime_Closed);
			txtData.PreviewKeyDown += new KeyEventHandler(txtData_PreviewKeyDown);
			btnDown.Click += new RoutedEventHandler(btnAbaixo_Click);
			btnUp.Click += new RoutedEventHandler(btnAcima_Click);
			btnOpenPopUp.Click += new RoutedEventHandler(btnAbreListbox_Click);
			btnOpenPopUp.PreviewMouseLeftButtonDown += new MouseButtonEventHandler(btnOpenPopUp_PreviewMouseLeftButtonDown);
			txtData.GotMouseCapture += new MouseEventHandler(txtData_GotMouseCapture);
			btnDown.PreviewKeyDown += new KeyEventHandler(btnDown_PreviewKeyDown);
			btnUp.PreviewKeyDown += new KeyEventHandler(btnUp_PreviewKeyDown);
			btnOpenPopUp.PreviewKeyDown += new KeyEventHandler(btnOpenPopUp_PreviewKeyDown);
			minute.PreviewMouseLeftButtonUp += new MouseButtonEventHandler(minute_MouseLeftButtonUp);
			hour.PreviewMouseLeftButtonUp += new MouseButtonEventHandler(hour_MouseLeftButtonUp);
            txtData.GotFocus += new RoutedEventHandler(txtData_GotFocus);
            //txtData.LostFocus += new RoutedEventHandler(txtData_LostFocus);

            this.PreviewGotKeyboardFocus += new KeyboardFocusChangedEventHandler(SinacorTimePicker_PreviewGotKeyboardFocus);
            this.PreviewLostKeyboardFocus += new KeyboardFocusChangedEventHandler(SinacorTimePicker_PreviewLostKeyboardFocus);
			Binding TextBinding = new Binding("InternalDate");
			TextBinding.Mode = BindingMode.TwoWay;
			TextBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
			TextBinding.RelativeSource = RelativeSource.TemplatedParent;
			this.txtData.SetBinding(SinacorTextBox.TextProperty, TextBinding);

			selectDatePart(0, true);
			ValidationConstrutor();
			CreateLists();

            LostFocusAllElements(this);

            //btnOpenPopUp.Focusable = false;
            //btnUp.Focusable = false;
            //btnDown.Focusable = false;
		}

        void SinacorTimePicker_PreviewLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
        {
            MaskController(false);
        }

        void SinacorTimePicker_PreviewGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
        {
            MaskController(true);
        }

        //void txtData_LostFocus(object sender, RoutedEventArgs e)
        //{
        //    if (txtData.Text == DateMaskFormat)
        //        txtData.Text = "";
        //}

        void txtData_GotFocus(object sender, RoutedEventArgs e)
        {
            if(txtData != null && txtData.CaretIndex > -1)
                selectDatePart(txtData.CaretIndex, true);
        }

        private void ChildLostFocus(object sender, RoutedEventArgs e)
        {
            if (IsAnyElementFocused(this))
                e.Handled = true;
            else
            {
                RaiseControlLostFocusEvent();
            }

        }

        protected override void OnLostFocus(RoutedEventArgs e)
        {
            UIElement elementWithFocus = Keyboard.FocusedElement as UIElement;

            if (IsAnyElementFocused(this))
                e.Handled = true;
            else
            {
                base.OnLostFocus(e);
            }
        }

        private void LostFocusAllElements(object control)
        {
            if (!(control is UIElement))
                return;

            ((UIElement)control).LostFocus += new RoutedEventHandler(ChildLostFocus);

            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(control as DependencyObject); i++)
            {
                UIElement child = VisualTreeHelper.GetChild(control as DependencyObject, i) as UIElement;

                if (child != null)
                {
                    child.LostFocus += new RoutedEventHandler(ChildLostFocus);
                    LostFocusAllElements(child);
                }
            }

        }

        private void RaiseControlLostFocusEvent()
        {
            RoutedEventArgs e = new RoutedEventArgs(InternalLostFocusEvent, this);
            this.RaiseEvent(e);
        }

        private bool IsAnyElementFocused(object control)
        {
            bool hasFocus = false;

            if (!(control is UIElement)) return hasFocus;

            if (PopUpTime.IsOpen || ((UIElement)control).IsFocused || ((UIElement)control).IsKeyboardFocused || ((UIElement)control).IsKeyboardFocusWithin)
            {
                hasFocus = true;
            }
            else
            {
                for (int i = 0; i < VisualTreeHelper.GetChildrenCount(control as DependencyObject); i++)
                {
                    UIElement child = VisualTreeHelper.GetChild(control as DependencyObject, i) as UIElement;

                    if (child != null)
                    {
                        if (child.IsFocused || child.IsKeyboardFocused || child.IsKeyboardFocusWithin)
                        {
                            hasFocus = true;
                            break;
                        }
                        else
                        {
                            hasFocus = IsAnyElementFocused(child);

                            if (hasFocus)
                            {
                                break;
                            }
                        }
                    }
                }
            }

            return hasFocus;
        }


        private void MaskController(bool showMask)
        {
            if (showMask)
            {
                if (txtData != null && String.IsNullOrEmpty(txtData.Text))
                    txtData.Text = DateMaskFormat;
            }
            else
            {
                if (txtData != null && txtData.Text == DateMaskFormat)
                    txtData.Text = "";
            }
        }

		public void sChanged(object sender, ScrollChangedEventArgs e)
		{
			ScrollViewer x = (ScrollViewer)e.OriginalSource;
			x.Height = 75.0;
		}

		protected virtual void UpdateValitadions()
		{
			if (this.ValidationRules.Contains(TimeValidationRuleName))
			{
				TimeValidationRule ValidationRule = this.ValidationRules[TimeValidationRuleName] as TimeValidationRule;
				if (ValidationRule != null)
				{
					ValidationRule.ErrorContent = InvalidDateErrorMessage;
					ValidationRule.IsEnabled = true;
				}
			}
			if (this.ValidationRules.Contains(RequiredValidationRuleName))
			{
				RequiredValidationRule reqValidation = this.ValidationRules[RequiredValidationRuleName] as RequiredValidationRule;
				if (reqValidation != null)
				{
					reqValidation.ErrorContent = RequiredErrorMessage;
					reqValidation.IsEnabled = this.IsRequired;
				}
			}
			//if (this.ValidationRules.Contains(RangeValidationRuleName))
			//{
			//    RangeValidationRule RangeValidation = this.ValidationRules[RangeValidationRuleName] as RangeValidationRule;
			//    if (RangeValidation != null)
			//    {
			//        RangeValidation.ErrorContent = RangeOverflowErrorMessage;
			//        string _MaxTime = "23:59";
			//        string _MinTime = "00:00";
			//        RangeValidation.Maximum = _MaxTime;
			//        RangeValidation.Minimum = _MinTime;
			//        RangeValidation.IsEnabled = true;
			//    }
			//}
		}
		protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
		{
			base.OnPropertyChanged(e);

            if (e.Property == ValueProperty)
            {
                RoutedEventArgs eValueChanged = new RoutedEventArgs(ValueChangedEvent, this);
                this.RaiseEvent(eValueChanged);
            }

			OnPropertyChanged(e.Property.Name);
		}
		protected Binding GetBindingOfInputProperty()
		{
			return BindingOperations.GetBinding(this, SinacorTimePicker.ValueProperty);
		}

		public SinacorTimePicker()
		{
			ValidationManager.InitializeValidation(this);

			this.BehaviorPolicyAdapter = new BehaviorPolicyAdapter(this);

			MaxTime = DateTime.MaxValue;
			MinTime = DateTime.MinValue;

			this.PropertyChanged += new PropertyChangedEventHandler(Sinacor_PropertyChanged);
			this.Loaded += new RoutedEventHandler(Sinacor_Loaded);

            System.Windows.DataObject.AddPastingHandler(this, new System.Windows.DataObjectPastingEventHandler(OnPasting));

		}

		bool ValidateInputedTime(string value)
		{
			if (String.IsNullOrEmpty(value))
				return false;
			DateTime Result;
			string date = "01/01/2000" + " " + value.ToString();
			if (DateTime.TryParseExact(date, "dd/MM/yyyy HH:mm", null, DateTimeStyles.None, out Result))
				return true;
			else
				return false;
		}
		void PopUpTime_Closed(object sender, EventArgs e)
		{
			this.Validate();
		}
		void txtData_GotMouseCapture(object sender, MouseEventArgs e)
		{
			selectDatePart(((SinacorTextBox)sender).CaretIndex, true);
			e.Handled = true;
		}
		void minute_PreviewKeyDown(object sender, KeyEventArgs e)
		{
			e.Handled = true;
		}
		void hour_PreviewKeyDown(object sender, KeyEventArgs e)
		{
			e.Handled = true;
		}
		void btnOpenPopUp_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
		{
			_isOpen = PopUpTime.IsOpen;
		}
		void btnAcima_Click(object sender, RoutedEventArgs e)
		{
            IncreaseValue();
            txtData.Focus();
		}
		void btnAbreListbox_Click(object sender, RoutedEventArgs e)
		{
			if (String.IsNullOrEmpty(txtData.Text.Trim()) || (!String.IsNullOrEmpty(txtData.Text.Trim()) && ValidateInputedTime(txtData.Text.Trim())))
			{
				if (!_isOpen)
				{
					PopUpTime.IsOpen = true;
					_isOpen = true;
					atualizaListbox();
				}
				else
				{
					PopUpTime.IsOpen = false;
					_isOpen = false;
				}
				e.Handled = true;
			}
			else
			{
				txtData.Text = "00:00";
				PopUpTime.IsOpen = true;
				_isOpen = true;
				atualizaListbox();
				e.Handled = true;
			}
		}
		void btnAbaixo_Click(object sender, RoutedEventArgs e)
		{
            DecreaseValue();
            txtData.Focus();
		}
		void txtData_PreviewKeyDown(object sender, KeyEventArgs e)
		{
            if ((e.Key == Key.D0 || e.Key == Key.NumPad0) && Keyboard.Modifiers == ModifierKeys.None)
            {
                e.Handled = true;
                validateInput('0');
            }
            else if ((e.Key == Key.D1 || e.Key == Key.NumPad1) && Keyboard.Modifiers == ModifierKeys.None)
            {
                e.Handled = true;
                validateInput('1');
            }
            else if ((e.Key == Key.D2 || e.Key == Key.NumPad2) && Keyboard.Modifiers == ModifierKeys.None)
            {
                e.Handled = true;
                validateInput('2');
            }
            else if ((e.Key == Key.D3 || e.Key == Key.NumPad3) && Keyboard.Modifiers == ModifierKeys.None)
            {
                e.Handled = true;
                validateInput('3');
            }
            else if ((e.Key == Key.D4 || e.Key == Key.NumPad4) && Keyboard.Modifiers == ModifierKeys.None)
            {
                e.Handled = true;
                validateInput('4');
            }
            else if ((e.Key == Key.D5 || e.Key == Key.NumPad5) && Keyboard.Modifiers == ModifierKeys.None)
            {
                e.Handled = true;
                validateInput('5');
            }
            else if ((e.Key == Key.D6 || e.Key == Key.NumPad6) && Keyboard.Modifiers == ModifierKeys.None)
            {
                e.Handled = true;
                validateInput('6');
            }
            else if ((e.Key == Key.D7 || e.Key == Key.NumPad7) && Keyboard.Modifiers == ModifierKeys.None)
            {
                e.Handled = true;
                validateInput('7');
            }
            else if ((e.Key == Key.D8 || e.Key == Key.NumPad8) && Keyboard.Modifiers == ModifierKeys.None)
            {
                e.Handled = true;
                validateInput('8');
            }
            else if ((e.Key == Key.D9 || e.Key == Key.NumPad9) && Keyboard.Modifiers == ModifierKeys.None)
            {
                e.Handled = true;
                validateInput('9');
            }
            else if (e.Key == Key.Back)
            {
                e.Handled = true;
                removeDigit();
            }
            else if (e.Key == Key.Home)
            {
                e.Handled = true;
                index = 0;
            }
            else if (e.Key == Key.End)
            {
                e.Handled = true;
                index = 3;
            }
            else if (e.Key == Key.Delete)
            {
                e.Handled = true;
                deleteBlock();
            }
            else if (e.Key == Key.Tab)
            {
                switch (selection)
                {
                    case enmTypeSelection.Hour:
                        if ((Keyboard.Modifiers == ModifierKeys.Shift))
                        {
                            selectDatePart(0, true);
                        }
                        else
                        {
                            e.Handled = true;
                            selectDatePart(3, true);
                        }
                        break;
                    case enmTypeSelection.Minute:

                        if (Keyboard.Modifiers == ModifierKeys.Shift)
                        {
                            e.Handled = true;
                            selectDatePart(0, true);
                        }
                        else
                        {
                            selectDatePart(3, true);
                        }
                        break;
                }
                return;
            }
            else if (e.Key == Key.Up)
            {
                e.Handled = true;
                IncreaseValue();
                txtData.Focus();
                return;
            }
            else if (e.Key == Key.Down)
            {
                e.Handled = true;
                DecreaseValue();
                txtData.Focus();
                return;
            }
            else if (e.Key == Key.Right)
            {
                e.Handled = true; 
                
                switch (selection)
                {
                    case enmTypeSelection.Hour:
                        selectDatePart(3, true);
                        break;
                    case enmTypeSelection.Minute:
                        selectDatePart(0, true);
                        break;
                }
 
                return;
            }
            else if (e.Key == Key.Left)
            {
                e.Handled = true;

                switch (selection)
                {
                    case enmTypeSelection.Hour:
                        selectDatePart(3, true);
                        break;
                    case enmTypeSelection.Minute:
                        selectDatePart(0, true);
                        break;
                }

                return;
            }
            else if (e.Key == Key.Z)
            {
                e.Handled = true;

                if (Keyboard.Modifiers == ModifierKeys.Control)
                {
                    if (oldTime.Count > 0)
                    {
                        txtData.Text = oldTime[oldTime.Count - 1].Hour.ToString("00") + ":" + oldTime[oldTime.Count - 1].Minute.ToString("00");
                        oldTime.Remove(oldTime[oldTime.Count - 1]);
                    }
                }
            }
            else if (e.Key != Key.Enter)
            {
                e.Handled = true;
            }
		}
		void minute_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
		{

		}
		void btnOpenPopUp_PreviewKeyDown(object sender, KeyEventArgs e)
		{
			txtData.Focus();
			if (e.Key == Key.Up)
			{
                IncreaseValue();
                e.Handled = true;
                return;
			}
			else if (e.Key == Key.Down)
			{
                DecreaseValue();
                e.Handled = true;
                return;
			}
			else if (e.Key == Key.Right)
			{
				switch (selection)
				{
					case enmTypeSelection.Hour:
						selectDatePart(3, true);
						break;
					case enmTypeSelection.Minute:
						selectDatePart(0, true);
						break;
				}
				e.Handled = true;
				return;
			}
			else if (e.Key == Key.Left)
			{
				switch (selection)
				{
					case enmTypeSelection.Hour:
						selectDatePart(3, true);
						break;
					case enmTypeSelection.Minute:
						selectDatePart(0, true);
						break;
				}
				e.Handled = true;
				return;
			}
		}
		void btnUp_PreviewKeyDown(object sender, KeyEventArgs e)
		{
			txtData.Focus();
			if (e.Key == Key.Up)
			{
				IncreaseValue();
				return;
			}
			else if (e.Key == Key.Down)
			{
				DecreaseValue();
				return;
			}
			else if (e.Key == Key.Right)
			{
				switch (selection)
				{
					case enmTypeSelection.Hour:
						selectDatePart(3, true);
						break;
					case enmTypeSelection.Minute:
						selectDatePart(0, true);
						break;
					default:
						selectDatePart(3, true);
						break;
				}
				e.Handled = true;
				return;
			}
			else if (e.Key == Key.Left)
			{
				switch (selection)
				{
					case enmTypeSelection.Hour:
						selectDatePart(3, true);
						break;
					case enmTypeSelection.Minute:
						selectDatePart(0, true);
						break;
					default:
						selectDatePart(3, true);
						break;
				}
				e.Handled = true;
				return;
			}
		}
		void btnDown_PreviewKeyDown(object sender, KeyEventArgs e)
		{
			txtData.Focus();
			if (e.Key == Key.Up)
			{
				IncreaseValue();
				return;
			}
			else if (e.Key == Key.Down)
			{
				DecreaseValue();
				return;
			}
			else if (e.Key == Key.Right)
			{
				switch (selection)
				{
					case enmTypeSelection.Hour:
						selectDatePart(3, true);
						break;
					case enmTypeSelection.Minute:
						selectDatePart(0, true);
						break;
					default:
						selectDatePart(3, true);
						break;
				}
				e.Handled = true;
				return;
			}
			else if (e.Key == Key.Left)
			{
				switch (selection)
				{
					case enmTypeSelection.Hour:
						selectDatePart(3, true);
						break;
					case enmTypeSelection.Minute:
						selectDatePart(0, true);
						break;
					default:
						selectDatePart(3, true);
						break;
				}
				e.Handled = true;
				return;
			}
		}
		void minute_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
		{
			string value;
			index = 2;
			value = ((Selector)(sender)).SelectedItem.ToString();
			foreach (char item in value.ToCharArray())
				validateInput(item);
			atualizaListboxClick();
		}
		void hour_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
		{
			string value;
			index = 0;
			value = ((Selector)(sender)).SelectedItem.ToString();
			foreach (char item in value.ToCharArray())
				validateInput(item);
			atualizaListboxClick();
		}
		void atualizaListboxClick()
		{
			string[] arrHourMinute;
			int intHour, intMinute;
			DateTime datTemp = DateTime.Now;

			arrHourMinute = txtData.Text.Replace("PM", "").Replace("AM", "").Split(':');
			try
			{
				intHour = Convert.ToInt32(arrHourMinute[0]);

			}
			catch
			{
				intHour = 0;

			}
			try
			{
				intMinute = Convert.ToInt32(arrHourMinute[1]);
			}
			catch
			{
				intMinute = 0;
			}
			hour.Items.MoveCurrentToPosition(intHour);
			//hour.ScrollIntoView(hour.Items[intHour + 2]);// ScrollIntoView para 3 elementos
			if (hour.SelectedValue == null)
				hour.SelectedValue = intHour.ToString("00");
			hour.ScrollIntoView(hour.Items[0]);
			hour.ScrollIntoView(hour.Items[intHour + 4]);// ScrollIntoView para 5 elementos

			hour.SelectedIndex = intHour + 2;
			hour.Focus();

			minute.Items.MoveCurrentToPosition(intMinute);
			//minute.ScrollIntoView(minute.Items[intMinute + 2]);// ScrollIntoView para 3 elementos
			if (minute.SelectedValue == null)
				minute.SelectedValue = intMinute.ToString("00");
			minute.ScrollIntoView(minute.Items[0]);
			minute.ScrollIntoView(minute.Items[intMinute + 4]);// ScrollIntoView para 5 elementos

			minute.SelectedIndex = intMinute + 2;
			minute.Focus();
		}
		void ValidationConstrutor()
		{
			Binding ValueBinding = new Binding("Value");
			ValueBinding.Mode = BindingMode.TwoWay;
			ValueBinding.Converter = new TimeConverter();
			ValueBinding.UpdateSourceTrigger = UpdateSourceTrigger.Explicit;
			ValueBinding.RelativeSource = RelativeSource.Self;
			this.SetBinding(SinacorTimePicker.InternalDateProperty, ValueBinding);

			RequiredValidationRule reqValidation = new RequiredValidationRule(this, SinacorTimePicker.InternalDateProperty);
			reqValidation.Name = RequiredValidationRuleName;

			this.ValidationRules.Add(reqValidation);
			reqValidation.ErrorContent = RequiredErrorMessage;
			reqValidation.IsEnabled = this.IsRequired;

			TimeValidationRule validation = new TimeValidationRule(this, SinacorTimePicker.InternalDateProperty);
			this.ValidationRules.Add(validation);
			validation.Name = TimeValidationRuleName;
			validation.ErrorContent = InvalidDateErrorMessage;
			validation.IsEnabled = true;

			//RangeValidationRule rangeValidation = new RangeValidationRule(this, SinacorTimePicker.InternalDateProperty);
			//rangeValidation.Name = RangeValidationRuleName;
			//this.ValidationRules.Add(rangeValidation);

			//string _MaxTime = "23:59";
			//string _MinTime = "00:00";

			//rangeValidation.Maximum = (IComparable)_MaxTime;
			//rangeValidation.Minimum = (IComparable)_MinTime;
			//rangeValidation.ErrorContent = RangeOverflowErrorMessage;
			//rangeValidation.IsEnabled = true;

            EventValidationTrigger trigger = new EventValidationTrigger(ValidationTriggerScope.Self, InternalLostFocusEvent);
            //EventValidationTrigger trigger = new EventValidationTrigger(ValidationTriggerScope.Self, LostFocusEvent);
            trigger.ContinueRoutingOnError = true;
			if (!this.ValidationTriggers.Contains(trigger))
			{
				this.ValidationTriggers.Add(trigger);
			}
		}
		void selectDatePart(int intIndex, bool bolAlteraIndex)
		{
			if (intIndex == 0 || intIndex == 1)
			{
				if (bolAlteraIndex) this.index = 0;
				txtData.SelectionStart = 0;
				txtData.SelectionLength = 2;
				selection = enmTypeSelection.Hour;
			}
			else if (intIndex == 2 || intIndex == 3 || intIndex == 4)
			{
				if (bolAlteraIndex) this.index = 3;
				txtData.SelectionStart = 3;
				txtData.SelectionLength = 2;
				selection = enmTypeSelection.Minute;
			}
		}
		void CreateLists()
		{
			hour.Name = "ListHoras";
			FrameworkElementFactory f = new FrameworkElementFactory(typeof(UniformGrid));
			//f.SetValue(UniformGrid.RowsProperty, 27);// 3 elementos
			f.SetValue(UniformGrid.RowsProperty, 29);//5 elementos
			f.SetValue(UniformGrid.ColumnsProperty, 1);
			hour.ItemsPanel = new ItemsPanelTemplate(f);
			//hour.ItemsSource = new string[] { "", "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "" };//hour para 3 elemntos
			hour.ItemsSource = new string[] { "22 ", "23 ", "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "00 ", "01 " };
			//PopUpTime.SetValue(ScrollViewer.HorizontalScrollBarVisibilityProperty, ScrollBarVisibility.Hidden);
			//PopUpTime.SetValue(ScrollViewer.VerticalScrollBarVisibilityProperty, ScrollBarVisibility.Hidden);
			hour.Width = 50;
			hour.Background = Brushes.Transparent;
			hour.AddHandler(ScrollViewer.PreviewMouseWheelEvent, new MouseWheelEventHandler(scrollListbox));
			hour.AddHandler(ScrollViewer.ScrollChangedEvent, new ScrollChangedEventHandler(sChanged));
			minute.Name = "ListMinutos";
			FrameworkElementFactory f2 = new FrameworkElementFactory(typeof(UniformGrid));
			//f2.SetValue(UniformGrid.RowsProperty, 62);//3 elementos
			f2.SetValue(UniformGrid.RowsProperty, 64);//5 elementos
			f2.SetValue(UniformGrid.ColumnsProperty, 1);
			minute.ItemsPanel = new ItemsPanelTemplate(f2);
			//minute.ItemsSource = new string[] { "", "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "" };//Minutes para 3 elementos
			minute.ItemsSource = new string[] { "58 ", "59 ", "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "00 ", "01 " };//Minutes para 5 elementos
			minute.SetValue(ScrollViewer.HorizontalScrollBarVisibilityProperty, ScrollBarVisibility.Hidden);
			minute.SetValue(ScrollViewer.VerticalScrollBarVisibilityProperty, ScrollBarVisibility.Hidden);
			minute.Width = 50;
			minute.Background = Brushes.Transparent;
			minute.AddHandler(ScrollViewer.PreviewMouseWheelEvent, new MouseWheelEventHandler(scrollListbox));
			hour.SetValue(Panel.ZIndexProperty, 1);
			minute.SetValue(Panel.ZIndexProperty, 1);
			hour.SetValue(Grid.ColumnProperty, 0);
			minute.SetValue(Grid.ColumnProperty, 1);
			hour.PreviewKeyDown += new KeyEventHandler(hour_PreviewKeyDown);
			minute.PreviewKeyDown += new KeyEventHandler(minute_PreviewKeyDown);
		}

        protected void OnPasting(object sender, DataObjectPastingEventArgs e)
        {
            Object ObjetoPasted = e.DataObject.GetData(System.Windows.DataFormats.StringFormat);
            bool ConteudoValido = false;
            string NovoTexto = "";

            //O Paste só será efetuado se for uma string
            if (ObjetoPasted is String && ObjetoPasted != null)
            {
                NovoTexto = (string)ObjetoPasted;

                if (!String.IsNullOrEmpty(NovoTexto))
                    ConteudoValido = ValidateValue(NovoTexto);
            }

            //Cancela o pasting de conteúdo
            e.CancelCommand();
            e.Handled = true;

            //Acrescenta o past pelo value
            if (ConteudoValido)
                this.Value = DateTime.Parse(NovoTexto);
        }

        public static readonly RoutedEvent ValueChangedEvent = EventManager.RegisterRoutedEvent("ValueChanged", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(SinacorTimePicker));
        /// <summary>
        /// Evento disparado depois do inicio da aplicação de um estilo 
        /// </summary>
        public event RoutedEventHandler ValueChanged
        {
            add { AddHandler(ValueChangedEvent, value); }
            remove { RemoveHandler(ValueChangedEvent, value); }
        }

        internal static readonly RoutedEvent InternalLostFocusEvent = EventManager.RegisterRoutedEvent("InternalLostFocus", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(SinacorTimePicker));
        /// <summary>
        /// Evento disparado depois do inicio da aplicação de um estilo 
        /// </summary>
        internal event RoutedEventHandler InternalLostFocus
        {
            add { AddHandler(InternalLostFocusEvent, value); }
            remove { RemoveHandler(InternalLostFocusEvent, value); }
        }

        #region ValidateValue
        private bool ValidateValue(string text)
        {
            DateTime dateValue;

            if (DateTime.TryParse(text, out dateValue))
                return true;
            else
                return false;
        }
        #endregion

        void atualizaListbox()
		{
			string[] arrHourMinute;
			int intHour, intMinute;
			DateTime datTemp = DateTime.Now;

			try
			{
				arrHourMinute = txtData.Text.Replace("PM", "").Replace("AM", "").Split(':');

				intHour = Convert.ToInt32(arrHourMinute[0]);
				intMinute = Convert.ToInt32(arrHourMinute[1]);
			}
			catch
			{
				intHour = 0;
				intMinute = 0;
			}

			hour.Items.MoveCurrentToPosition(intHour);
			//hour.ScrollIntoView(hour.Items[intHour + 2]);// ScrollIntoView para 3 elementos
			if (hour.SelectedValue == null)
				hour.SelectedValue = intHour.ToString("00");

			if (Int32.Parse(hour.SelectedValue.ToString()) > intHour)
				hour.ScrollIntoView(hour.Items[intHour]);
			else if (Int32.Parse(hour.SelectedValue.ToString()) < intHour)
				hour.ScrollIntoView(hour.Items[intHour + 4]);// ScrollIntoView para 5 elementos

			hour.SelectedIndex = intHour + 2;
			hour.Focus();

			minute.Items.MoveCurrentToPosition(intMinute);
			//minute.ScrollIntoView(minute.Items[intMinute + 2]);// ScrollIntoView para 3 elementos
			if (minute.SelectedValue == null)
				minute.SelectedValue = intMinute.ToString("00");

			if (Int32.Parse(minute.SelectedValue.ToString()) > intMinute)
				minute.ScrollIntoView(minute.Items[intMinute]);
			else if (Int32.Parse(minute.SelectedValue.ToString()) < intMinute)
				minute.ScrollIntoView(minute.Items[intMinute + 4]);// ScrollIntoView para 5 elementos

			minute.SelectedIndex = intMinute + 2;
			minute.Focus();
		}
		void atualizaListboxScroll()
		{
			string[] arrHourMinute;
			int intHour, intMinute;
			DateTime datTemp = DateTime.Now;

			try
			{
				arrHourMinute = txtData.Text.Replace("PM", "").Replace("AM", "").Split(':');

				intHour = Convert.ToInt32(arrHourMinute[0]);
				intMinute = Convert.ToInt32(arrHourMinute[1]);
			}
			catch
			{
				intHour = 0;
				intMinute = 0;
			}

			hour.Items.MoveCurrentToPosition(intHour);
			//hour.ScrollIntoView(hour.Items[intHour + 2]);// ScrollIntoView para 3 elementos
			if (hour.SelectedValue == null)
				hour.SelectedValue = intHour.ToString("00");
			hour.ScrollIntoView(hour.Items[intHour + 4]);// ScrollIntoView para 5 elementos

			hour.SelectedIndex = intHour + 2;
			hour.Focus();

			minute.Items.MoveCurrentToPosition(intMinute);
			//minute.ScrollIntoView(minute.Items[intMinute + 2]);// ScrollIntoView para 3 elementos
			if (minute.SelectedValue == null)
				minute.SelectedValue = intMinute.ToString("00");
			minute.ScrollIntoView(minute.Items[intMinute + 4]);// ScrollIntoView para 5 elementos

			minute.SelectedIndex = intMinute + 2;
			minute.Focus();
		}
		void validateInput(char chrEntrada)
		{
			if (String.IsNullOrEmpty(txtData.Text))
				txtData.Text = DateMaskFormat;
			string strTextoAnterior = txtData.Text;
			string strAnterior, strProximo, strNovaString;

			if (!String.IsNullOrEmpty(chrEntrada.ToString().Trim()))
			{
				if (index >= 5)
					index = 0;
				if (index == 2)
					index = 3;
				strAnterior = strTextoAnterior.Substring(0, index);
				strProximo = strTextoAnterior.Substring(index + 1);
				strNovaString = strAnterior + chrEntrada + strProximo;
				txtData.Text = strNovaString;
				index++;
				txtData.CaretIndex = index;
				selectDatePart(index, false);
			}
		}
		void removeDigit()
		{
			if (String.IsNullOrEmpty(txtData.Text))
			{
				txtData.Text = DateMaskFormat;
			}
			string strTextoAnterior = txtData.Text;
			switch (selection)
			{
				case enmTypeSelection.Hour:
					txtData.Text = "__" + txtData.Text.Substring(2, 3);
					selectDatePart(3, true);
					break;
				case enmTypeSelection.Minute:
					txtData.Text = txtData.Text.Substring(0, 3) + "__";
					selectDatePart(0, true);
					break;
			}
		}
		void deleteBlock()
		{
			if (String.IsNullOrEmpty(txtData.Text))
			{
				txtData.Text = DateMaskFormat;
			}
			string strTextoData = string.Empty;
			switch (selection)
			{
				case enmTypeSelection.Hour:
					txtData.Text = "__" + txtData.Text.Substring(2, 3);
					selectDatePart(0, true);
					break;
				case enmTypeSelection.Minute:
					txtData.Text = txtData.Text.Substring(0, 3) + "__";
					selectDatePart(3, true);
					break;
			}
		}
		void IncreaseValue()
		{
			adjustDate(enmTypeAdjust.Increase);
			txtData.Focus();

            //btnUp.Focusable = true;
            //btnUp.Focus();
            //btnUp.Focusable = false;
		}
		void DecreaseValue()
		{
			adjustDate(enmTypeAdjust.Decrease);
			txtData.Focus();

            //btnDown.Focusable = true;
            //btnDown.Focus();
            //btnDown.Focusable = false;
		}
		void adjustDate(enmTypeAdjust enmAjuste)
		{
			if (String.IsNullOrEmpty(txtData.Text))
			{
				txtData.Text = DateMaskFormat;
			}
			DateTime datTemp = DateTime.Now;
			//string strNumero;
			int intHour, intMinute;
			string[] arrHourMinute;

			try
			{
				arrHourMinute = txtData.Text.Replace("PM", "").Replace("AM", "").Split(':');

				//strNumero = txtData.Text.Substring(0, 2);
				//intHour = Convert.ToInt32(strNumero);

				intHour = Convert.ToInt32(arrHourMinute[0]);
				intMinute = Convert.ToInt32(arrHourMinute[1]);

			}
			catch
			{
				//intHour = datTemp.Hour;
				//intMinute = datTemp.Minute;
				intHour = 0;
				intMinute = 0;
			}

			/*
			try
			{
				strNumero = txtData.Text.Substring(3, 2);
				intMinute = Convert.ToInt32(strNumero);
			}
			catch { intMinute = datTemp.Minute; }
			*/

			switch (selection)
			{
				case enmTypeSelection.Hour:
					switch (enmAjuste)
					{
						case enmTypeAdjust.Increase:
							intHour++;
							if (intHour > 23) intHour = 0;
							break;
						case enmTypeAdjust.Decrease:
							intHour--;
							if (intHour < 0) intHour = 23;
							break;
					}
					//					strNumero = intHour.ToString("00");
					index = 0;
					//					txtData.Text = strNumero + txtData.Text.Substring(2, 3);
					break;

				case enmTypeSelection.Minute:
					switch (enmAjuste)
					{
						case enmTypeAdjust.Increase:
							intMinute++;
							if (intMinute > 59) intMinute = 0;
							break;
						case enmTypeAdjust.Decrease:
							intMinute--;
							if (intMinute < 0) intMinute = 59;
							break;
					}
					//					strNumero = intMinute.ToString("00");
					index = 3;
					//					txtData.Text = txtData.Text.Substring(0, 3) + strNumero;
					break;
			}

			txtData.Text = intHour.ToString("00") + ":" + intMinute.ToString("00");

			selectDatePart(index, false);

			atualizaListboxScroll();
		}
		void scrollListbox(Object sender, MouseWheelEventArgs e)
		{
			ListBox lb = (ListBox)sender;

			int index = lb.Items.CurrentPosition;

			if (lb.Name == "ListHoras")
			{
				selection = enmTypeSelection.Hour;
			}
			else
			{
				selection = enmTypeSelection.Minute;
			}

			if (e.Delta < 0)
			{
				if (index == lb.Items.Count - 1)
				{
					index = index - 1;
					lb.Items.MoveCurrentToPrevious();
				}
				else
				{
					lb.Items.MoveCurrentToNext();
					IncreaseValue();
				}
			}
			else
			{
				if (index == 0)
				{
					index = 1;
					lb.Items.MoveCurrentToNext();
				}
				else
				{
					lb.Items.MoveCurrentToPrevious();
					DecreaseValue();
				}
			}

			if ((index >= 0) && (index <= lb.Items.Count - 1))
			{
				//lb.ScrollIntoView(lb.Items[index]);//3 elementos
				lb.ScrollIntoView(lb.Items[index + 1]);//5 elementos
				lb.SelectedItem = lb.Items.CurrentPosition;
				lb.Focus();
			}
			if (selection == enmTypeSelection.Hour)
			{
				if (lb.SelectedValue == hour.Items[hour.Items.Count - 3])
				{
					lb.ScrollIntoView(lb.Items[27]);
					lb.SelectedItem = lb.Items.CurrentPosition;
					lb.Focus();
				}
				else if (lb.SelectedValue == hour.Items[2])
				{
					lb.ScrollIntoView(lb.Items[0]);
					lb.SelectedItem = lb.Items.CurrentPosition;
					lb.Focus();
				}
			}
			else if (selection == enmTypeSelection.Minute)
			{
				if (lb.SelectedValue == minute.Items[minute.Items.Count - 3])
				{
					lb.ScrollIntoView(lb.Items[63]);
					lb.SelectedItem = lb.Items.CurrentPosition;
					lb.Focus();
				}
				else if (lb.SelectedValue == minute.Items[2])
				{
					lb.ScrollIntoView(lb.Items[0]);
					lb.SelectedItem = lb.Items.CurrentPosition;
					lb.Focus();
				}
			}
		}
		void Sinacor_Loaded(object sender, RoutedEventArgs e)
		{
			this.Drop += new DragEventHandler(SinacorTimePicker_Drop);
			this.DragEnter += new DragEventHandler(SinacorTimePicker_DragEnter);
			SinacorChangesMonitorContainer container = ChangesMonitorManager.GetParentChangesMonitorContainer(this);
			if (container != null)
				container.CleaningChanges += new RoutedEventHandler(container_CleaningChanges);

            //Aplica estilo para sina
            TemplateHelper.ApplyGridTemplate(this);
		}
		void SinacorTimePicker_DragEnter(object sender, DragEventArgs e)
		{
			e.Handled = true;
		}
		void SinacorTimePicker_Drop(object sender, DragEventArgs e)
		{
			e.Handled = true;
		}
		void container_CleaningChanges(object sender, RoutedEventArgs e)
		{
			this._sourceObjectHashCode = null;
		}
		void Sinacor_PropertyChanged(object sender, PropertyChangedEventArgs e)
		{
			if (this.IsChangeMonitored && e.PropertyName == ChangesMonitorManager.GetDefaultPropertyAttribute(this))
			{
				bool hasChanges = true;

				Binding bind = GetBindingOfInputProperty();
				//se tiver biding associado 
				if (bind != null)
				{
					//recuperar o hashCode do objeto source do binding
					int? objectHashCode = this.GetHashCodeOfSourceObject(bind);

					//se nao houve um objeto source dos dados (ou seja, se nao houver binding)
					//disparar sempre o evento de indicacao de alteracao
					if (objectHashCode.HasValue)
					{
						//se for um objeto diferente do atual, significa que houve uma alteração no bindig, sendo assim
						//nao dever ser disparado o evento de indicacao de alteracao para o changes monitor
						if (_sourceObjectHashCode != objectHashCode)
						{
							_sourceObjectHashCode = objectHashCode;
							hasChanges = false;
						}
					}
					////se havia um objeto source e nao existe mais, limpar o hashcode e nao disparar o evento de indicacao de alteracao
					else
					{
						_sourceObjectHashCode = objectHashCode;
						hasChanges = false;
					}
				}

				if (hasChanges)
				{
					RoutedEventArgs controlHasChangesEventArgs = new RoutedEventArgs(ChangesMonitorManager.ControlHasChangedEvent, this);
					this.RaiseEvent(controlHasChangesEventArgs);
				}
			}
		}
		void OnPropertyChanged(string propertyName)
		{
			if (PropertyChanged != null)
				PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
		}
	}

	public class TimeConverter : IValueConverter
	{
		public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
		{
			if (value != null)
			{
				DateTime result = new DateTime(2000, 01, 01, ((DateTime)value).Hour, ((DateTime)value).Minute, 00);
				return result.Hour.ToString("00") + ":" + result.Minute.ToString("00");
			}
			return "";
		}
		public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
		{
			if (value == null || value.ToString() == "__:__" || String.IsNullOrEmpty(value.ToString()))
				return null;
			DateTime Result;
			string date = "01/01/2000" + " " + value.ToString();
			if (DateTime.TryParseExact(date, "dd/MM/yyyy HH:mm", null, DateTimeStyles.None, out Result))
				return Result;
			else
				return null;
		}
	}
}